package top.zhangjianyong.blog.aspect;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import top.zhangjianyong.blog.annotation.Permission;
import top.zhangjianyong.blog.cache.UserCache;
import top.zhangjianyong.blog.enums.RespCode;
import top.zhangjianyong.blog.enums.RoleKeys;
import top.zhangjianyong.blog.response.ApiResponse;

/**
 * 角色权限切面
 *
 * @author zhangjianyong
 * @since 2024/7/29 下午5:25
 */
@Slf4j
@Aspect
@Component
@Order(0)
public class PermissionAspect {

  @Pointcut(
      "@annotation(top.zhangjianyong.blog.annotation.Permission) "
          + "||@within(top.zhangjianyong.blog.annotation.Permission)")
  public void pointCut() {}

  @Around("pointCut()")
  public Object permission(ProceedingJoinPoint pjp) throws Throwable {
    log.info("permission ...");
    Permission annotation = getAnnotation(pjp);
    if (annotation != null) { // 有注解需要检验权限，没有注解不做权限控制
      RoleKeys[] roleKeys = annotation.roles(); // 允许访问的权限
      List<String> roles = UserCache.roles();
      if (Arrays.stream(roleKeys).noneMatch(key -> key.hasRole(roles))) {
        return ApiResponse.fail(RespCode.USER_NOT_ALLOWED);
      }
    }
    return pjp.proceed();
  }

  private Permission getAnnotation(ProceedingJoinPoint pjp) {
    MethodSignature signature = (MethodSignature) pjp.getSignature();
    Method method = signature.getMethod();
    Permission annotation = method.getAnnotation(Permission.class);
    if (annotation == null) { // 方法注解如果不存在，找类的注解
      Class<?> targetClass = pjp.getTarget().getClass();
      annotation = targetClass.getAnnotation(Permission.class);
    }
    return annotation;
  }
}
